package demo;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
import java.util.*;
import java.util.logging.Logger;

import javax.persistence.EntityManager;
import javax.persistence.Query;
import javax.servlet.http.*;


@SuppressWarnings("serial")
public class MyTrackServlet extends HttpServlet {
	private static final Logger log = Logger.getLogger(MyTrackServlet.class.getName());	
	//static final long ONE_MINUTES_IN_MILLIS = 60000;
	public String imei = "";
	//public Date NextSMSDate = null;
	
	public void doGet(HttpServletRequest req, HttpServletResponse resp)
			throws IOException {
		Map map = req.getParameterMap();
		Set s = map.keySet();
		for (Iterator it = s.iterator(); it.hasNext(); ) {
			String key = (String)it.next();
			String[] values = (String[])map.get(key);
			log.info(key + "=>" +values[0]);
		}

		imei = req.getParameter("imei");
		String rmc = req.getParameter("rmc");
		TrackDataAO ao = new TrackDataAO();
		ao.add(imei, rmc);
			
		resp.setContentType("text/plain");
		//resp.getWriter().println("OK" + " " + latlng + " " + GeofenceLatLng);
		resp.getWriter().println("OK" + " " + getPhoneNo() + " " + getsimno() + " " + getTrackerName() + " " + getLastLocation());
		

		String latlng = getLatLng(rmc);
		String[] latlngArray = latlng.split(",");
		double CurrentLat = Double.parseDouble(latlngArray[0]);
		double CurrentLng = Double.parseDouble(latlngArray[1]);
		String PreviousLatLng = getLastLocation();
		String[] PreviousLatLngArray = PreviousLatLng.split(",");
		
		try{
		List<PermanentGeofenceData> mList = getPermanentFenceData(imei);
		PermanentGeofenceData tData = mList.get(0);
		String PermanentGeofenceLat = tData.getlatitude();
		String PermanentGeofenceLng = tData.getlongitude();
		String PermanentGeofenceName = tData.getName();
		double dPermanentGeofenceLat = Double.parseDouble(PermanentGeofenceLat);
		double dPermanentGeofenceLng = Double.parseDouble(PermanentGeofenceLng);
		String PermanentGeofenceLatLng = PermanentGeofenceLat + "," + PermanentGeofenceLng;
		String PermanentgeofenceDistance = tData.getdistance();
		double dPermanentGeofenceDistance = Double.parseDouble(PermanentgeofenceDistance);

		boolean checkCurrentToPermanentCircle = checkInsideCircle(CurrentLat,CurrentLng,dPermanentGeofenceLat,dPermanentGeofenceLng,dPermanentGeofenceDistance);
		boolean checkPreviousToPermanentCircle = checkInsideCircle(Double.parseDouble(PreviousLatLngArray[0]),Double.parseDouble(PreviousLatLngArray[1]),dPermanentGeofenceLat,dPermanentGeofenceLng,dPermanentGeofenceDistance);

		if(checkCurrentToPermanentCircle == false){
			addOutsidePermanentGeofence(imei,PermanentGeofenceName,latlngArray[0],latlngArray[1]);
		}
		
		Date MessageSentDate = new Date();
		long a = MessageSentDate.getTime();
		Date b = new Date(a + (8 * 60 * 60 * 1000));		
		
		if(checkPreviousToPermanentCircle == true){
			resp.getWriter().println("Inside Previous Permanent Circle");
			if(checkCurrentToPermanentCircle == false){
				resp.getWriter().println("Moved out of the Permanent Circle");
				
				String urlParameters = "MobileNo=" + getPhoneNo() + "&Message=http://maps.google.com/maps?q=" + latlngArray[0] + "," + latlngArray[1] + "; Tracker with SIM No: " + getsimno() + " had moved out of the Permanent geofence at " + b + "&SMSAccount=FYPJ10&SMSPassword=512280";
				//String urlParameters = "MobileNo=" + "84330671" + "&Message=" + getTrackerName() + ", http://maps.google.com/maps?q=" + latlngArray[0] + "," + latlngArray[1] + "; Tracker with SIM No: " + getsimno() + " had moved out of the Permanent geofence." + "&SMSAccount=FYPJ10&SMSPassword=512280";
				URL url = new URL("https://dprj.sit.nyp.edu.sg/SMSWebService/sms.asmx/sendMessage");
				URLConnection conn = url.openConnection();

				conn.setDoOutput(true);
						
				OutputStreamWriter writer = new OutputStreamWriter(conn.getOutputStream());
				
				//Uncomment this line to activate the Geofence SMS function
				writer.write(urlParameters);
				writer.flush();
						
				String line;
				BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream()));
						
				while ((line = reader.readLine()) != null){
					System.out.println(line);
				}
						
				writer.close();
				reader.close();	

			}
		}
		}
		catch(Exception ex){}
		
		try{
		List<TemporaryGeofenceData> nList = getTemporaryFenceData(imei);
		TemporaryGeofenceData uData = nList.get(0);
		String TemporaryGeofenceLat = uData.getlatitude();
		String TemporaryGeofenceLng = uData.getlongitude();
		double dTemporaryGeofenceLat = Double.parseDouble(TemporaryGeofenceLat);
		double dTemporaryGeofenceLng = Double.parseDouble(TemporaryGeofenceLng);
		String TemporaryGeofenceLatLng = TemporaryGeofenceLat + "," + TemporaryGeofenceLng;
		String TemporarygeofenceDistance = uData.getdistance();
		double dTemporaryGeofenceDistance = Double.parseDouble(TemporarygeofenceDistance);		
		
		boolean checkCurrentToTemporaryCircle = checkInsideCircle(CurrentLat,CurrentLng,dTemporaryGeofenceLat,dTemporaryGeofenceLng,dTemporaryGeofenceDistance);
		boolean checkPreviousToTemporaryCircle = checkInsideCircle(Double.parseDouble(PreviousLatLngArray[0]),Double.parseDouble(PreviousLatLngArray[1]),dTemporaryGeofenceLat,dTemporaryGeofenceLng,dTemporaryGeofenceDistance);
		
		Date MessageSentDate = new Date();
		long a = MessageSentDate.getTime();
		Date b = new Date(a + (8 * 60 * 60 * 1000));	
		
		if(checkPreviousToTemporaryCircle == true){
			resp.getWriter().println("Inside Previous Temporary Circle");
			if(checkCurrentToTemporaryCircle == false){
				resp.getWriter().println("Moved out of the Temporary Circle");
				DeleteTemporaryFenceData();
				
				String urlParameters = "MobileNo=" + getPhoneNo() + "&Message=http://maps.google.com/maps?q=" + latlngArray[0] + "," + latlngArray[1] + "; Tracker with SIM No: " + getsimno() + " had moved out of the Temporary geofence at " + b + "&SMSAccount=FYPJ10&SMSPassword=512280";
				//String urlParameters = "MobileNo=" + "84330671" + "&Message=" + getTrackerName() + ", http://maps.google.com/maps?q=" + latlngArray[0] + "," + latlngArray[1] + "; Tracker with SIM No: " + getsimno() + " had moved out of the Temporary geofence." + "&SMSAccount=FYPJ10&SMSPassword=512280";
				URL url = new URL("https://dprj.sit.nyp.edu.sg/SMSWebService/sms.asmx/sendMessage");
				URLConnection conn = url.openConnection();

				conn.setDoOutput(true);
						
				OutputStreamWriter writer = new OutputStreamWriter(conn.getOutputStream());
				
				//Uncomment this line to activate the Geofence SMS function
				writer.write(urlParameters);
				writer.flush();
						
				String line;
				BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream()));
						
				while ((line = reader.readLine()) != null){
					System.out.println(line);
				}
						
				writer.close();
				reader.close();	

			}
		}
		}
		catch(Exception e){}
		/*
		if(checkCurrentToPermanentCircle == true){
			resp.getWriter().println("Inside Circle");
		}
		if(checkCurrentToPermanentCircle == false){
			//Date AlertDate = getAlertDate();
			//if(checkCurrentDateMoreAlertDate(AlertDate) == true){
				//add(imei,geofenceDistance,GeofenceLat,GeofenceLng,latlngArray[0],latlngArray[1]);
				resp.getWriter().println("Outside Circle and SMS alert had been sent out");
				
				String urlParameters = "MobileNo=" + getPhoneNo() + "&Message=" + getTrackerName() + ", http://maps.google.com/maps?q=" + latlngArray[0] + "," + latlngArray[1] + "; Tracker with SIM No: " + getsimno() + " had moved out of the geofence." + "&SMSAccount=FYPJ10&SMSPassword=512280";
				URL url = new URL("https://dprj.sit.nyp.edu.sg/SMSWebService/sms.asmx/sendMessage");
				URLConnection conn = url.openConnection();

				conn.setDoOutput(true);
						
				OutputStreamWriter writer = new OutputStreamWriter(conn.getOutputStream());
				
				//Uncomment this line to activate the Geofence SMS function
				//writer.write(urlParameters);
				writer.flush();
						
				String line;
				BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream()));
						
				while ((line = reader.readLine()) != null){
					System.out.println(line);
				}
						
				writer.close();
				reader.close();	
			}
			else
				resp.getWriter().println("Outside Circle");
		}
		*/
		
		
		
		/*PrintWriter out = resp.getWriter();
		out.println("<html><head>"
				+ "<script src='http://maps.googleapis.com/maps/api/js?key=AIzaSyAR33uUSrW-Nc3NWqPUZV30Anh1DOS9oto&sensor=false' type='text/javascript></script>"
				+ "<script type='text/javascript'>function initialize(){}"
				+ "</script></head><body onload='initialize();'></html>");*/

	}
	
	public void DeleteTemporaryFenceData() {
		
		EntityManager em = EMF.get().createEntityManager();
		
		Query q = em.createQuery("delete from TemporaryGeofenceData d where imei = '" + imei + "'");
		int i = q.executeUpdate();
		em.close();
	}
	
	public String getLastLocation() {
			List<TrackData> raw = new ArrayList<TrackData>();
			EntityManager em = EMF.get().createEntityManager();
			// Query q = em.createQuery("select from TrackData d");
			Query q = em.createQuery("select d from TrackData d where imei='"
					+ imei + "'");
			raw = q.getResultList();
			em.close();
			
			TrackData data = raw.get(raw.size()-1);
			String Gprmc = data.getGprmc();
			String getLatLng = getLatLng(Gprmc);
			
			return getLatLng;
	}
	
	public String getPhoneNo() {
		List<User> list = new ArrayList<User>();
		EntityManager em = EMF.get().createEntityManager();
		Query q = em.createQuery("select d from User d where imei='"
				+ imei + "'");
		list = q.getResultList();
		em.close();
		User data = list.get(0);
		String phoneNo = data.getPhoneno();

		return phoneNo;
	}
	
	public String getsimno() {
		List<User> list = new ArrayList<User>();
		EntityManager em = EMF.get().createEntityManager();
		Query q = em.createQuery("select d from User d where imei='"
				+ imei + "'");
		list = q.getResultList();
		em.close();
		User data = list.get(0);
		String simno = data.getSimno();

		return simno;
	}
	
	public String getTrackerName() {
		List<User> list = new ArrayList<User>();
		EntityManager em = EMF.get().createEntityManager();
		Query q = em.createQuery("select d from User d where imei='"
				+ imei + "'");
		list = q.getResultList();
		em.close();
		User data = list.get(0);
		String trackerName = data.getTrackername();

		return trackerName;
	}
	
	/*
	public boolean checkCurrentDateMoreAlertDate(Date AlertDate){
		Date currentDate = new Date();
		long a = currentDate.getTime();
		Date b = new Date(a + (8 * 60 * 60 * 1000));
		//long c = b.getTime();
		if(b.getTime() >= AlertDate.getTime() || b.getTime() == AlertDate.getTime()){
			return true;
		}
		else
			return false;
	
	}
	
	public Date getAlertDate() {
		Date alertDate = null;
		try{
		EntityManager em = EMF.get().createEntityManager();
		Query q = em.createQuery("select d from OutsideGeofenceMessage d where imei = '" + imei + "'");

		List<OutsideGeofenceMessage> raw = q.getResultList();
		OutsideGeofenceMessage data = raw.get(raw.size()-1);
		alertDate = data.getMessageSentAlertDate();
		
		em.close();
		return alertDate;
		}
		catch (Exception ex){

			addNull(imei);
			EntityManager em = EMF.get().createEntityManager();
			Query q = em.createQuery("select d from OutsideGeofenceMessage d where imei = '" + imei + "'");

			List<OutsideGeofenceMessage> raw = q.getResultList();
			OutsideGeofenceMessage data = raw.get(raw.size()-1);		
			alertDate = data.getMessageSentAlertDate();
			
			em.close();
			return alertDate;
			
		}
	}
	
	public boolean addNull(String imei) {
		OutsideGeofenceMessage OutsideMessage = new OutsideGeofenceMessage();
		EntityManager em = EMF.get().createEntityManager();
		OutsideMessage.setImei(imei);
		
		Date MessageSentDate = new Date();
		long a = MessageSentDate.getTime();
		Date b = new Date(a + (8 * 60 * 60 * 1000));
				
		OutsideMessage.setMessageSentDate(b);
		OutsideMessage.setMessageSentAlertDate(b);
		em.persist(OutsideMessage);
		em.close();
		return true;
	}
	
	
	
	public boolean add(String imei, String geodistance, String geolatitude, String geolongitude, String latitude, String longitude) {
		OutsideGeofenceMessage OutsideMessage = new OutsideGeofenceMessage();
		EntityManager em = EMF.get().createEntityManager();
		OutsideMessage.setImei(imei);
		OutsideMessage.setGeodistance(geodistance);
		OutsideMessage.setGeolatitude(geolatitude);
		OutsideMessage.setGeolongitude(geolongitude);
		OutsideMessage.setlatitude(latitude);
		OutsideMessage.setlongitude(longitude);
		
		Date MessageSentDate = new Date();
		long a = MessageSentDate.getTime();
		Date b = new Date(a + (8 * 60 * 60 * 1000));
		
		long current = b.getTime();
		Date add20minutes = new Date(current + (20 * ONE_MINUTES_IN_MILLIS));
		NextSMSDate = add20minutes;
				
		OutsideMessage.setMessageSentDate(b);
		//OutsideMessage.setMessageSentAlertDate(add20minutes);
		em.persist(OutsideMessage);
		em.close();
		return true;
	}	*/
	
	public boolean addOutsidePermanentGeofence(String imei,String geofenceName, String latitude, String longitude) {
		OutsideGeofence OutsidePermanentGeofence = new OutsideGeofence();
		EntityManager em = EMF.get().createEntityManager();
		OutsidePermanentGeofence.setImei(imei);
		//OutsidePermanentGeofence.setGeodistance(geodistance);
		//OutsidePermanentGeofence.setGeolatitude(geolatitude);
		//OutsidePermanentGeofence.setGeolongitude(geolongitude);
		OutsidePermanentGeofence.setGeofencename(geofenceName);
		OutsidePermanentGeofence.setlatitude(latitude);
		OutsidePermanentGeofence.setlongitude(longitude);
		OutsidePermanentGeofence.setGeofenceType("Permanent");
		
		Date MessageSentDate = new Date();
		long a = MessageSentDate.getTime();
		Date b = new Date(a + (8 * 60 * 60 * 1000));
				
		OutsidePermanentGeofence.setDateTime(b);
		//OutsideMessage.setMessageSentAlertDate(add20minutes);
		em.persist(OutsidePermanentGeofence);
		em.close();
		return true;
	}	
	
	public double power(double numberGiven, double power){
		double output = Math.pow(numberGiven,power);
		return output;
	}
	
	public boolean checkInsideCircle(double GivenX, double GivenY, double GeoX, double GeoY, double distance){
		double radius = (distance/1000) / 100;
		double radius2 = power(radius,2);
		double powerX = power((GivenX-GeoX),2);
		double powerY = power((GivenY-GeoY),2);
		double sumXY = powerX + powerY;
		
		if(sumXY <= radius2){
			return true;
		}
		else{
			return false;
		}
	}

	
	public void doPost(HttpServletRequest req, HttpServletResponse resp)
			throws IOException {
		doGet(req,resp);
	}
	
	public List<PermanentGeofenceData> getPermanentFenceData(String imei) {
		List<PermanentGeofenceData> list = new ArrayList<PermanentGeofenceData>();
		EntityManager em = EMF.get().createEntityManager();
		Query q = em.createQuery("select d from PermanentGeofenceData d where imei='"
				+ imei + "'");
		list = q.getResultList();
		em.close();

		return list;
	}
	
	public List<TemporaryGeofenceData> getTemporaryFenceData(String imei) {
		List<TemporaryGeofenceData> list = new ArrayList<TemporaryGeofenceData>();
		EntityManager em = EMF.get().createEntityManager();
		Query q = em.createQuery("select d from TemporaryGeofenceData d where imei='"
				+ imei + "'");
		list = q.getResultList();
		em.close();

		return list;
	}
	
	private String getLatLng(String gprmc) {
		String[] tokens = gprmc.split(",");
		String latlng = "";
		if (tokens.length > 5) {
			String latStr = tokens[3];
			String lngStr = tokens[5];
			double lat = convert(latStr);
			double lng = convert(lngStr);

			latlng = Double.toString(lat) + "," + Double.toString(lng);
		}

			return latlng;
	}
	
	private double convert(String str) {
		double d = -1;
		String[] tokens = str.split("\\.");

		String degree = tokens[0].substring(0, tokens[0].length() - 2);
		String min = tokens[0].substring(tokens[0].length() - 2) + "."
				+ tokens[1];
		d = Integer.parseInt(degree) + Double.parseDouble(min) / 60.0;

		return d;
	}
		
}
